/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.aries.cdi.container.internal.container; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Dictionary; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.Bean; import javax.inject.Singleton; import org.apache.aries.cdi.container.internal.util.Conversions; import org.apache.aries.cdi.container.internal.util.Maps; import org.osgi.framework.Bundle; import org.osgi.framework.PrototypeServiceFactory; import org.osgi.framework.ServiceFactory; import org.osgi.framework.ServiceRegistration; import org.osgi.service.cdi.annotations.Service; import org.osgi.util.converter.TypeReference; public class ServiceDeclaration { @SuppressWarnings({ "rawtypes"}) public ServiceDeclaration(Service service, Bean bean, CreationalContext creationalContext) { _service = service; _bean = bean; _creationalContext = creationalContext; Dictionary<String, Object> properties = new Hashtable<>(); for (Object object : bean.getQualifiers()) { Annotation annotation = (Annotation)object; Map<String, Object> map = Conversions.c().convert( annotation).sourceAs(annotation.annotationType()).to(_mapType); for (Map.Entry<String, Object> entry : map.entrySet()) { properties.put(entry.getKey(), entry.getValue()); } } for (Entry<String, Object> entry : Maps.map(_service.property()).entrySet()) { properties.put(entry.getKey(), entry.getValue()); } _properties = properties; } @SuppressWarnings("rawtypes") public Bean getBean() { return _bean; } public String[] getClassNames() { List<String> classNames = new ArrayList<>(); Class<?>[] types = _service.type(); if (types.length > 0) { for (Type type : types) { classNames.add(type.getTypeName()); } } else { types = _bean.getBeanClass().getInterfaces(); if (types.length > 0) { for (Type type : types) { classNames.add(type.getTypeName()); } } else { classNames.add(_bean.getBeanClass().getName()); } } return classNames.toArray(new String[classNames.size()]); } public Dictionary<String, Object> getProperties() { return _properties; } @SuppressWarnings({ "unchecked" }) public Object getServiceInstance() { Class<?> scope = _bean.getScope(); if (Singleton.class.isAssignableFrom(scope)) { return _bean.create(_creationalContext); } else if (ApplicationScoped.class.isAssignableFrom(scope)) { return new BundleScopeWrapper(); } return new PrototypeScopeWrapper(); } private static final TypeReference<Map<String, Object>> _mapType = new TypeReference<Map<String, Object>>(){}; @SuppressWarnings("rawtypes") private final Bean _bean; @SuppressWarnings("rawtypes") private final CreationalContext _creationalContext; private final Dictionary<String, Object> _properties; private final Service _service; @SuppressWarnings({"rawtypes", "unchecked"}) private class BundleScopeWrapper implements ServiceFactory { @Override public Object getService(Bundle bundle, ServiceRegistration registration) { return _bean.create(_creationalContext); } @Override public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { _bean.destroy(service, _creationalContext); } } @SuppressWarnings({"rawtypes", "unchecked"}) private class PrototypeScopeWrapper implements PrototypeServiceFactory { @Override public Object getService(Bundle bundle, ServiceRegistration registration) { return _bean.create(_creationalContext); } @Override public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { _bean.destroy(service, _creationalContext); } } }